using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Lcygcc.Infrastructure.Utility.IOC
{
	public class AppDomainTypeFinder : ITypeFinder
	{
		private bool ignoreReflectionErrors = true;
		private bool loadAppDomainAssemblies = true;
		private string assemblySkipLoadingPattern = "^System|^mscorlib|^Microsoft|^AjaxControlToolkit|^Antlr3|^Autofac|^AutoMapper|^Castle|^ComponentArt|^CppCodeProvider|^DotNetOpenAuth|^EntityFramework|^EPPlus|^FluentValidation|^ImageResizer|^itextsharp|^log4net|^MaxMind|^MbUnit|^MiniProfiler|^Mono.Math|^MvcContrib|^Newtonsoft|^NHibernate|^nunit|^Org.Mentalis|^PerlRegex|^QuickGraph|^Recaptcha|^Remotion|^RestSharp|^Rhino|^Telerik|^Iesi|^TestDriven|^TestFu|^UserAgentStringLibrary|^VJSharpCodeProvider|^WebActivator|^WebDev|^WebGrease";
		private string assemblyRestrictToLoadingPattern = ".*";
		private IList<string> assemblyNames = new List<string>();
		public virtual AppDomain App
		{
			get
			{
				return AppDomain.CurrentDomain;
			}
		}
		public bool LoadAppDomainAssemblies
		{
			get
			{
				return this.loadAppDomainAssemblies;
			}
			set
			{
				this.loadAppDomainAssemblies = value;
			}
		}
		public IList<string> AssemblyNames
		{
			get
			{
				return this.assemblyNames;
			}
			set
			{
				this.assemblyNames = value;
			}
		}
		public string AssemblySkipLoadingPattern
		{
			get
			{
				return this.assemblySkipLoadingPattern;
			}
			set
			{
				this.assemblySkipLoadingPattern = value;
			}
		}
		public string AssemblyRestrictToLoadingPattern
		{
			get
			{
				return this.assemblyRestrictToLoadingPattern;
			}
			set
			{
				this.assemblyRestrictToLoadingPattern = value;
			}
		}
		public IEnumerable<Type> FindClassesOfType<T>(bool onlyConcreteClasses = true)
		{
			return this.FindClassesOfType(typeof(T), onlyConcreteClasses);
		}
		public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, bool onlyConcreteClasses = true)
		{
			return this.FindClassesOfType(assignTypeFrom, this.GetAssemblies(), onlyConcreteClasses);
		}
		public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
		{
			return this.FindClassesOfType(typeof(T), assemblies, onlyConcreteClasses);
		}
		public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
		{
			List<Type> list = new List<Type>();
			try
			{
				foreach (Assembly current in assemblies)
				{
					Type[] array = null;
					try
					{
						array = current.GetTypes();
					}
					catch
					{
						if (!this.ignoreReflectionErrors)
						{
							throw;
						}
					}
					if (array != null)
					{
						Type[] array2 = array;
						for (int i = 0; i < array2.Length; i++)
						{
							Type type = array2[i];
							if (assignTypeFrom.IsAssignableFrom(type) || (assignTypeFrom.IsGenericTypeDefinition && this.DoesTypeImplementOpenGeneric(type, assignTypeFrom)))
							{
								if (!type.IsInterface)
								{
									if (onlyConcreteClasses)
									{
										if (type.IsClass && !type.IsAbstract)
										{
											list.Add(type);
										}
									}
									else
									{
										list.Add(type);
									}
								}
							}
						}
					}
				}
			}
			catch (ReflectionTypeLoadException ex)
			{
				string text = string.Empty;
				Exception[] loaderExceptions = ex.LoaderExceptions;
				for (int i = 0; i < loaderExceptions.Length; i++)
				{
					Exception ex2 = loaderExceptions[i];
					text = text + ex2.Message + Environment.NewLine;
				}
				Exception ex3 = new Exception(text, ex);
				Debug.WriteLine(ex3.Message, new object[]
				{
					ex3
				});
				throw ex3;
			}
			return list;
		}
		public virtual IList<Assembly> GetAssemblies()
		{
			List<string> addedAssemblyNames = new List<string>();
			List<Assembly> list = new List<Assembly>();
			if (this.LoadAppDomainAssemblies)
			{
				this.AddAssembliesInAppDomain(addedAssemblyNames, list);
			}
			this.AddConfiguredAssemblies(addedAssemblyNames, list);
			return list;
		}
		private void AddAssembliesInAppDomain(List<string> addedAssemblyNames, List<Assembly> assemblies)
		{
			Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies2.Length; i++)
			{
				Assembly assembly = assemblies2[i];
				if (this.Matches(assembly.FullName))
				{
					if (!addedAssemblyNames.Contains(assembly.FullName))
					{
						assemblies.Add(assembly);
						addedAssemblyNames.Add(assembly.FullName);
					}
				}
			}
		}
		protected virtual void AddConfiguredAssemblies(List<string> addedAssemblyNames, List<Assembly> assemblies)
		{
			foreach (string current in this.AssemblyNames)
			{
				Assembly assembly = Assembly.Load(current);
				if (!addedAssemblyNames.Contains(assembly.FullName))
				{
					assemblies.Add(assembly);
					addedAssemblyNames.Add(assembly.FullName);
				}
			}
		}
		public virtual bool Matches(string assemblyFullName)
		{
			return !this.Matches(assemblyFullName, this.AssemblySkipLoadingPattern) && this.Matches(assemblyFullName, this.AssemblyRestrictToLoadingPattern);
		}
		protected virtual bool Matches(string assemblyFullName, string pattern)
		{
			return Regex.IsMatch(assemblyFullName, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
		}
		protected virtual void LoadMatchingAssemblies(string directoryPath)
		{
			List<string> list = new List<string>();
			foreach (Assembly current in this.GetAssemblies())
			{
				list.Add(current.FullName);
			}
			if (Directory.Exists(directoryPath))
			{
				string[] files = Directory.GetFiles(directoryPath, "Lcygcc.*.dll");
				for (int i = 0; i < files.Length; i++)
				{
					string assemblyFile = files[i];
					try
					{
						AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyFile);
						if (this.Matches(assemblyName.FullName) && !list.Contains(assemblyName.FullName))
						{
							this.App.Load(assemblyName);
						}
					}
					catch (BadImageFormatException ex)
					{
						Trace.TraceError(ex.ToString());
					}
				}
			}
		}
		protected virtual bool DoesTypeImplementOpenGeneric(Type type, Type openGeneric)
		{
			bool result;
			try
			{
				Type genericTypeDefinition = openGeneric.GetGenericTypeDefinition();
				Type[] array = type.FindInterfaces((Type objType, object objCriteria) => true, null);
				for (int i = 0; i < array.Length; i++)
				{
					Type type2 = array[i];
					if (type2.IsGenericType)
					{
						bool flag = genericTypeDefinition.IsAssignableFrom(type2.GetGenericTypeDefinition());
						result = flag;
						return result;
					}
				}
				result = false;
			}
			catch
			{
				result = false;
			}
			return result;
		}
	}
}
